import pulpcore.Input;
import pulpcore.Stage;
import pulpcore.scene.Scene2D;
import java.util.Random;

/** Used to represent the game logic. */
public class PokemonCatcher extends Scene2D
{
	// TODO: We need to decide on branches' vertical proportion in relation to the background
	/** The proportion that the branches should be at vertically. */
	private static final double BRANCH_Y_PROPORTION = .5 / 3;
	// TODO We need to decide on seesaw's vertical proportion in relation to the background
	/** The proportion that the seesaw should be at vertically. */
	private static final double SEESAW_Y_PROPORTION = 2.5 / 3;
	/** The branch that corresponds with the active player. */
	private Branch activeBranch;
	/** The player that the user is currently controlling. */
	private Player activePlayer;
	/** Token moving across stage. */
	private Token activeToken;
	/** The background of the game. */
	private Background background;
	/** The branch on the left side of the game. */
	private Branch leftBranch;
	/** The player on the left side of the game. */
	private Player leftPlayer;
	/** The branch on the right side of the game. */
	private Branch rightBranch;
	/** The player on the right side of the game. */
	private Player rightPlayer;
	/** The seesaw that players jump onto and jump off of. */
	private Seesaw seesaw;

	/*
	 * (non-Javadoc)
	 * @see pulpcore.scene.Scene#load()
	 */
	@Override
	public void load()
	{
		// TODO We need to decide on background image
		background = new Background("Background.png");
		add(background);
		// TODO We need to decide on branch image
		// TODO: We need to decide on left branch horizontal proportion in relation to the background
		leftBranch = new Branch("Branch.png", 0, BRANCH_Y_PROPORTION);
		// TODO: We need to decide on right branch vertical proportion in relation to the background
		rightBranch = new Branch(leftBranch.getImage().mirror(), 1, BRANCH_Y_PROPORTION);
		add(leftBranch);
		add(rightBranch);
		activeBranch = leftBranch;
		// TODO We need to decide on seesaw image
		// TODO We need to decide on seesaw horizontal proportion in relation to the background
		seesaw = new Seesaw("Seesaw.png", 1.5 / 3, SEESAW_Y_PROPORTION);
		add(seesaw);
		// TODO We need to decide on left player's image
		// TODO: We need to decide on left player's horizontal position in relation to the background
		leftPlayer = new Player("Tina.png", Player.VerticalState.ON_BRANCH, .5 / 3.0, BRANCH_Y_PROPORTION);
		// TODO We need to decide on right player's image
		// TODO We need to decide on right player's horizontal position in relation to the background
		rightPlayer = new Player("Annlin.png", Player.VerticalState.ON_SEESAW, 2.5 / 3.0, SEESAW_Y_PROPORTION);
		add(leftPlayer);
		add(rightPlayer);
		activePlayer = leftPlayer;
			
	}

	/*
	 * (non-Javadoc)
	 * @see pulpcore.scene.Scene2D#update(int)
	 */
	@Override
	public void update(final int elapsedTime)
	{
		UpdateSeesawState();
		UpdatePlayerHorizontalState();
		UpdatePlayerVerticalState();
		seesaw.Rotate(elapsedTime);
		activePlayer.MoveHorizontally(elapsedTime);
		activePlayer.MoveVertically(elapsedTime);
		updateTokenState();
		final Timer timer = new Timer(360000);
		timer.update(2000);
		if (timer.verify(2000)) {
			displayNewToken();
		}
	}

	/**
	 * Update player horizontal state.
	 */
	public void UpdatePlayerHorizontalState()
	{
		activePlayer.setHorizontalState(Player.HorizontalState.NOT_MOVING);
		if (activePlayer.getVerticalState() == Player.VerticalState.ON_SEESAW)
		{
			return;
		}
		if (Input.isDown(Input.KEY_LEFT) && Input.isDown(Input.KEY_RIGHT))
		{
			return;
		}
		else if (Input.isDown(Input.KEY_LEFT))
		{
			if (activePlayer.x.get() <= activePlayer.getLeftHorizontalLimit())
			{
				return;
			}
			activePlayer.setHorizontalState(Player.HorizontalState.MOVING_LEFT);
		}
		else if (Input.isDown(Input.KEY_RIGHT))
		{
			if (activePlayer.x.get() >= activePlayer.getRightHorizontalLimit())
			{
				return;
			}
			activePlayer.setHorizontalState(Player.HorizontalState.MOVING_RIGHT);
		}
	}

	/**
	 * Update player vertical state.
	 */
	public void UpdatePlayerVerticalState()
	{
		switch (activePlayer.getVerticalState())
		{
		case ON_BRANCH:
			if (Input.isDown(Input.KEY_SPACE))
			{
				activePlayer.setVerticalState(Player.VerticalState.JUMPING);
			}
			break;
		case JUMPING:
			if (activePlayer.y.get() <= Player.getCeiling())
			{
				activePlayer.setVerticalState(Player.VerticalState.FALLING);
			}
			break;
		case FALLING:
			if (activePlayer.intersects(seesaw))
			{
				activePlayer.setVerticalState(Player.VerticalState.ON_SEESAW);
				if (activePlayer == leftPlayer)
				{
					seesaw.setState(Seesaw.State.ROTATING_LEFT);
					activePlayer = rightPlayer;
					activeBranch = rightBranch;
				}
				else if (activePlayer == rightPlayer)
				{
					seesaw.setState(Seesaw.State.ROTATING_RIGHT);
					activePlayer = leftPlayer;
					activeBranch = leftBranch;
				}
			}
			break;
		case ON_SEESAW:
			activePlayer.setVerticalState(Player.VerticalState.FLYING);
			break;
		case FLYING:
			if (activePlayer.y.get() <= Player.getCeiling())
			{
				activePlayer.setVerticalState(Player.VerticalState.LANDING);
			}
			break;
		case LANDING:
			if (activePlayer.intersects(activeBranch))
			{
				activePlayer.setVerticalState(Player.VerticalState.ON_BRANCH);
			}
		}
	}

	/**
	 * Update seesaw state.
	 */
	public void UpdateSeesawState()
	{
		switch (seesaw.getState())
		{
		default:
		case NOT_ROTATING:
			return;
		case ROTATING_LEFT:
			if (seesaw.angle.get() <= (2 * Math.PI * -.03))
			{
				seesaw.setState(Seesaw.State.NOT_ROTATING);
			}
			break;
		case ROTATING_RIGHT:
			if (seesaw.angle.get() >= (2 * Math.PI * .03))
			{
				seesaw.setState(Seesaw.State.NOT_ROTATING);
			}
		}
	}

	/**
	 * Update token state.
	 */
	public void updateTokenState()
	{
		// removes tokens not visible on stage
		if ((activeToken.x.get() < 0) || (activeToken.x.get() > Stage.getWidth()))
		{
			activeToken.removeFromParent();
		}
		// remove active token
		if (activeToken.intersects(activePlayer))
		{
			activeToken.removeFromParent();
		}
	}// end UpdateTokenState
	
	
	/**
	 * Have tokens fly across screen
	 */
	public void displayNewToken() {
		
		Random gen = new Random();
		
		
		final String[]tokenList = { /*{ "hayes"},*/
				"Pikachu",
				"Bulbasaur" ,
				"Charmander" ,
				"Caterpie" ,
				"Weedle",
				"Meowth" ,
				"TeamRocket" ,
				"Snorlax" };
		
		int tIndex = gen.nextInt(tokenList.length);
		
		// timed release of each token...how to do that...
		Token newToken = new Token(tokenList[tIndex], Stage.getHeight()/2, .05, .05);
		add(newToken);
		
	}
	
	
}